﻿using PaddleOCRSharp;
using System;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Security;
using System.Windows.Forms;
using Tester.Components;

namespace Tester
{
    public partial class FormOCRwts : Form
    {
        public WTS wts = new WTS();

        private string fileFilter = "*.*|*.bmp;*.jpg;*.jpeg;*.tiff;*.tiff;*.png";

        private PaddleOCREngine engine;
        PaddleStructureEngine structengine;
        Bitmap bmp;
        OCRResult lastocrResult;
        string outpath = Path.Combine(Environment.CurrentDirectory, "out");
        DateTime dt1 = DateTime.Now;
        DateTime dt2 = DateTime.Now;

        public FormOCRwts()
        {
            InitializeComponent();

            imageView1.AllowDrop = true;
        }


        private void FormOCRwts_Load(object sender, EventArgs e)
        {
            if (!Directory.Exists(outpath))
            { Directory.CreateDirectory(outpath); }

            //自带轻量版中英文模型V4模型
            OCRModelConfig config = null;

            //服务器中英文模型
            // OCRModelConfig config = new OCRModelConfig();
            //string root = System.IO.Path.GetDirectoryName(typeof(OCRModelConfig).Assembly.Location);
            //string modelPathroot = root + @"\inferenceserver";
            //config.det_infer = modelPathroot + @"\ch_ppocr_server_v2.0_det_infer";
            //config.cls_infer = modelPathroot + @"\ch_ppocr_mobile_v2.0_cls_infer";
            //config.rec_infer = modelPathroot + @"\ch_ppocr_server_v2.0_rec_infer";
            //config.keys = modelPathroot + @"\ppocr_keys.txt";

            //英文和数字模型V3
            //OCRModelConfig config = new OCRModelConfig();
            //string root = PaddleOCRSharp.EngineBase.GetRootDirectory();
            //string modelPathroot = root + @"\en_v3";
            //config.det_infer = modelPathroot + @"\en_PP-OCRv3_det_infer";
            //config.cls_infer = modelPathroot + @"\ch_ppocr_mobile_v2.0_cls_infer";
            //config.rec_infer = modelPathroot + @"\en_PP-OCRv3_rec_infer";
            //config.keys = modelPathroot + @"\en_dict.txt";

            //车牌识别
            //OCRModelConfig config = new OCRModelConfig();
            //string root = System.IO.Path.GetDirectoryName(typeof(OCRModelConfig).Assembly.Location);
            //string modelPathroot = root + @"\car";
            //config.det_infer = modelPathroot + @"\det";
            //config.cls_infer = modelPathroot + @"\cls";
            //config.rec_infer = modelPathroot + @"\rec";
            //config.keys = modelPathroot + @"\ppocr_keys.txt";

            //斯拉夫语（俄语）
            //OCRModelConfig config = new OCRModelConfig();
            //string root = System.IO.Path.GetDirectoryName(typeof(OCRModelConfig).Assembly.Location);
            //string modelPathroot = root + @"\ru";
            //config.cls_infer = modelPathroot + @"\ch_ppocr_mobile_v2.0_cls_infer";

            //config.det_infer = modelPathroot + @"\Multilingual_PP-OCRv3_det_infer";
            //config.rec_infer = modelPathroot + @"\cyrillic_PP-OCRv3_rec_infer";
            //config.keys = modelPathroot + @"\cyrillic_dict.txt";



            //OCR参数
            OCRParameter oCRParameter = new OCRParameter();
            oCRParameter.cpu_math_library_num_threads = 10;//预测并发线程数
            oCRParameter.enable_mkldnn = true;//web部署该值建议设置为0,否则出错，内存如果使用很大，建议该值也设置为0.
            oCRParameter.cls = false; //是否执行文字方向分类；默认false
            oCRParameter.det = true;//是否开启方向检测，用于检测识别180旋转
            oCRParameter.use_angle_cls = false;//是否开启方向检测，用于检测识别180旋转
            oCRParameter.det_db_score_mode = true;//是否使用多段线，即文字区域是用多段线还是用矩形，
            oCRParameter.max_side_len = 1500;
            oCRParameter.rec_img_h = 48;
            oCRParameter.rec_img_w = 320;
            oCRParameter.det_db_thresh = 0.3f;
            oCRParameter.det_db_box_thresh = 0.618f;

            //初始化OCR引擎
            engine = new PaddleOCREngine(config, oCRParameter);

            //模型配置，使用默认值
            StructureModelConfig structureModelConfig = null;
            //表格识别参数配置，使用默认值
            StructureParameter structureParameter = new StructureParameter();
            structengine = new PaddleStructureEngine(structureModelConfig, structureParameter);
        }

        /// <summary>
        /// 本地文件表格
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolStripButtonOpenFile_Click(object sender, System.EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = fileFilter;
            if (ofd.ShowDialog() != DialogResult.OK) 
                return;

            var imagebyte = File.ReadAllBytes(ofd.FileName);
            bmp = new Bitmap(new MemoryStream(imagebyte));
            imageView1.Image = bmp;
            if (bmp == null)
                return;

            string result = structengine.StructureDetect(bmp);
            OCRStructureResult ocrStructureResult = engine.DetectStructure(bmp);
            ShowOCRResult(ocrStructureResult, result, Path.GetFileNameWithoutExtension(ofd.FileName));

            ///////
            dt1 = DateTime.Now;
            OCRResult ocrResult = engine.DetectText(bmp);
            dt2 = DateTime.Now;
            ShowOCRTextResult(ocrResult);
        }

        /// <summary>
        /// 识别截图表格
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolStripButtonShot_Click(object sender, EventArgs e)
        {
            this.Hide();

            System.Threading.Thread.Sleep(200);
            Application.DoEvents();

            ScreenCapturer.ScreenCapturerTool screenCapturer = new ScreenCapturer.ScreenCapturerTool();
            if (screenCapturer.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                bmp = (Bitmap)screenCapturer.Image;
                imageView1.Image = bmp;

                string result = structengine.StructureDetect(bmp);//表格识别，返回结果是html格式的表格形式
                OCRStructureResult ocrStructureResult = engine.DetectStructure(bmp);
                ShowOCRResult(ocrStructureResult, result, Path.GetRandomFileName());
                this.Show();


                dt1 = DateTime.Now;
                OCRResult ocrResult = engine.DetectText(bmp);
                dt2 = DateTime.Now;
                ShowOCRTextResult(ocrResult);

                for (int i=0; i<ocrResult.TextBlocks.Count; i++)
                {
                    if (ocrResult.TextBlocks[i].Text.Contains("产品名称"))
                    {
                        if (!ocrResult.TextBlocks[i+1].Text.Contains("版本号"))
                        {
                            wts.cpmc = ocrResult.TextBlocks[i + 1].Text;
                        }
                    }
                    if (ocrResult.TextBlocks[i].Text.Contains("版本号") )
                    {
                        if (!ocrResult.TextBlocks[i + 1].Text.Contains("单位名称"))
                        {
                            wts.cpmc = ocrResult.TextBlocks[i + 1].Text;
                        }
                    }

                    if (ocrResult.TextBlocks[i].Text.Contains("单位名称"))
                    {
                        if(i < ocrResult.TextBlocks.Count/2)
                            wts.wtdwmc = ocrResult.TextBlocks[i + 1].Text;
                        else
                            wts.scdwmc = ocrResult.TextBlocks[i + 1].Text;
                    }
                    if (ocrResult.TextBlocks[i].Text.Contains("单位地址"))
                    {
                        if (i < ocrResult.TextBlocks.Count / 2)
                            wts.wtdwdz = ocrResult.TextBlocks[i + 1].Text;
                        else
                            wts.scdwdz = ocrResult.TextBlocks[i + 1].Text;
                    }
                    if (ocrResult.TextBlocks[i].Text.Contains("联系人"))
                        wts.wtdwlxr = ocrResult.TextBlocks[i + 1].Text;
                    if (ocrResult.TextBlocks[i].Text.Contains("电话"))
                        wts.wtdwlxrdh = ocrResult.TextBlocks[i].Text.Split(new string[] { "：" }, StringSplitOptions.RemoveEmptyEntries)[1];

                }
            }

            #region 回显信息
            textBoxcpmc.Text = wts.cpmc;

            textBoxwtdwmc.Text = wts.wtdwmc;
            textBoxwtdwdz.Text = wts.wtdwdz;
            textBoxwtdwlxr.Text = wts.wtdwlxr;
            textBoxwtdwlyrdh.Text = wts.wtdwlxrdh;

            textBoxscdwmc.Text = wts.scdwmc;
            textBoxscdwdz.Text = wts.scdwdz;
            #endregion
        }


        /// <summary>
        /// 显示结果
        /// </summary>
        private void ShowOCRTextResult(OCRResult ocrResult)
        {
            string t = "简单显示";

            lastocrResult = ocrResult;
            richTextBox1.Clear();

            Bitmap bitmap = (Bitmap)this.imageView1.Image;
            try
            {
                using (Graphics g = Graphics.FromImage(bitmap))
                {
                    foreach (var item in ocrResult.TextBlocks)
                    {
                        g.DrawPolygon(new Pen(Brushes.Red, 2), item.BoxPoints.Select(x => new PointF() { X = x.X, Y = x.Y }).ToArray());
                    }
                }
                imageView1.Image = null;
                imageView1.Image = bitmap;
            }
            catch (Exception ex)
            {
                Bitmap bmp = new Bitmap(bitmap);

                using (Graphics g = Graphics.FromImage(bmp))
                {
                    foreach (var item in ocrResult.TextBlocks)
                    {
                        g.DrawPolygon(new Pen(Brushes.Red, 2), item.BoxPoints.Select(x => new PointF() { X = x.X, Y = x.Y }).ToArray());
                    }
                }
                imageView1.Image = null;
                imageView1.Image = bmp;
            }

            if (t == "简单显示")
            {
                foreach (var item in ocrResult.TextBlocks)
                {
                    richTextBox1.AppendText(item.Text + "\n");

                }
            }
            else if (t == "详细显示")
            {
                foreach (var item in ocrResult.TextBlocks)
                {
                    richTextBox1.AppendText(item.ToString() + "\n");
                }
            }



            richTextBox1.AppendText("-----------------------------------\n");
            richTextBox1.AppendText($"耗时：{(dt2 - dt1).TotalMilliseconds}ms\n");

        }
        
        /// <summary>
        /// 显示表格结果
        /// </summary>
        private void ShowOCRResult(OCRStructureResult ocrResult, string result, string name)
        {
            //string css = "<style>table{ border-spacing: 0pt;} td { border: 1px solid black;}</style>";
            //result = result.Replace("<html>", "<html>" + css);
            //string savefile = $"{Environment.CurrentDirectory}\\out\\{name}.html";
            //File.WriteAllText(savefile, result);
            ////打开网页查看效果
            //Process.Start("explorer.exe", savefile);

            //////
            int rowcount = ocrResult.RowCount;
            int colcount = ocrResult.ColCount;
            DataTable dataTable = new DataTable();
            for (int i = 0; i < colcount; i++)
            {
                dataTable.Columns.Add("Column" + (i + 1).ToString(), typeof(string));
            }
            for (int i = 0; i < rowcount; i++)
            {
                DataRow row = dataTable.Rows.Add();
                for (int j = 0; j < colcount; j++)
                {
                    row[j] = ocrResult.Cells.FirstOrDefault(x => x.Row == i && x.Col == j).Text;
                }
            }
            dataGridView1.DataSource = dataTable;
            dataGridView1.Show();
        }

        private void toolStripButtonOK_Click(object sender, EventArgs e)
        {

            this.DialogResult = DialogResult.OK;
        }
    }
}
